#include <dspSimulator/instruction/dint.h>


bool DINT::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return true;
}

void DINT::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                             std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> DINT::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<DINT> dint;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<30>(data, 2, 0b000100000000000001000000000000)) {
            dint = std::make_shared<DINT>(dspInstInfo->getAddress(), baseCycle);
            dint->s = data[1];
            dint->p = data[0];
        }
    }
    return dint;
}

void DINT::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {
//    GIE bit in TSR → SGIE bit in TSR
    auto dspMachine = std::dynamic_pointer_cast<DspMachine>(targetMachine);
    auto TSR = dspMachine->getRegisters()->getReg32ByName("TSR")->getDataPtr();
    auto GIE = *TSR & 0x1;
    if (GIE == 0) {
        *TSR = *TSR & 0xfffffffd;
    } else {
        *TSR = *TSR | 0x10;
    }
//    0 → GIE bit in TSR
    *TSR = *TSR & 0xfffffffe;
//    0 → GIE bit in CSR
    auto CSR = dspMachine->getRegisters()->getReg32ByName("CSR")->getDataPtr();
    *CSR = *CSR & 0xfffffffe;
}

std::string DINT::toString() const {
    return {"DINT"};
}

std::shared_ptr<DspInstruction> DINT::clone() {
    return std::make_shared<DINT>(*this);
}
